use libloading::{Library,Symbol};
use lazy_static::lazy_static;
use std::os::raw::{c_char,c_int,c_void};
include!("./const.rs");

struct LibraryInfo {
    JS_NewRuntime:Symbol<'static,unsafe extern fn() -> *mut JSRuntime>,
    JS_NewContext:Symbol<'static,unsafe extern fn(*mut JSRuntime) -> *mut JSContext>,
    JS_AddIntrinsicBaseObjects:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicDate:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicEval:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicStringNormalize:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicRegExpCompiler:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicRegExp:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicJSON:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicProxy:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicMapSet:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicTypedArrays:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_AddIntrinsicPromise:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_Eval:Symbol<'static,unsafe extern fn(*mut JSContext,*const c_char,usize,*const c_char,c_int) -> JSValue>,
    JS_GetException:Symbol<'static,unsafe extern fn(*mut JSContext) -> JSValue>,
    JS_GetGlobalObject:Symbol<'static,unsafe extern fn(*mut JSContext) -> JSValue>,
    JS_NewCFunction2:Symbol<'static,unsafe extern fn(*mut JSContext,JSCFunction,*const c_char,c_int,JSCFunctionEnum,c_int) -> JSValue>,
    JS_DefinePropertyValueStr:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue,*const c_char,JSValue,c_int) -> c_int>,
    JS_SetPropertyFunctionList:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue,*const JSCFunctionListEntry,c_int)>,
    JS_NewCModule:Symbol<'static,unsafe extern fn(*mut JSContext,*const c_char,JSModuleInitFunc) -> *mut JSModuleDef>,
    JS_AddModuleExportList:Symbol<'static,unsafe extern fn(*mut JSContext,*mut JSModuleDef,*const JSCFunctionListEntry,c_int) -> c_int>,
    JS_SetModuleExportList:Symbol<'static,unsafe extern fn(*mut JSContext,*mut JSModuleDef,*const JSCFunctionListEntry,c_int) -> c_int>,
    JS_FreeContext:Symbol<'static,unsafe extern fn(*mut JSContext)>,
    JS_Require:Symbol<'static,unsafe extern fn(*mut JSContext,*mut c_char,JSValue) -> JSValue>,
    JS_NewClassID:Symbol<'static,unsafe extern fn( *mut JSClassID) -> JSClassID>,
    JS_NewClass:Symbol<'static,unsafe extern fn( *mut JSRuntime,JSClassID,*const JSClassDef) -> c_int>,
    JS_NewObjectClass:Symbol<'static,unsafe extern fn(ctx:*mut JSContext,c_int) -> JSValue>,
    JS_SetOpaque:Symbol<'static,unsafe extern fn(JSValue,*mut c_void)>,
    JS_GetOpaque:Symbol<'static,unsafe extern fn(JSValue,JSClassID) -> *mut c_void>,
    JS_SetModuleLoaderFunc:Symbol<'static,unsafe extern fn(*mut JSRuntime,JSModuleNormalizeFunc,JSModuleLoaderFunc,*mut c_void)>,
    JS_ThrowReferenceError:Symbol<'static,unsafe extern fn(*mut JSContext,*const c_char,...) -> JSValue>,
    JS_FreeRuntime:Symbol<'static,unsafe extern fn(*mut JSRuntime)>,
    __JS_FreeValue:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue)>,
    JS_ToCStringLen2:Symbol<'static,unsafe extern fn(*mut JSContext,*mut usize,JSValue,c_int) -> *const c_char>,
    JS_FreeCString:Symbol<'static,unsafe extern fn(*mut JSContext,*const c_char)>,
    JS_IsFunction:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue) -> c_int>,
    JS_IsArray:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue) -> c_int>,
    JS_GetPropertyStr:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue,*const c_char) -> JSValue>,
    JS_GetPropertyUint32:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue,u32) -> JSValue>,
    JS_GetOwnPropertyNames:Symbol<'static,unsafe extern fn(*mut JSContext,*mut *mut JSPropertyEnum,*mut u32,JSValue,c_int) -> c_int>,
    JS_GetPropertyInternal:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue,JSAtom,JSValue,c_int) -> JSValue>,
    JS_AtomToString:Symbol<'static,unsafe extern fn(*mut JSContext,JSAtom) -> JSValue>,
    JS_FreeAtom:Symbol<'static,unsafe extern fn(*mut JSContext,JSAtom) -> JSValue>,
    js_free:Symbol<'static,unsafe extern fn(*mut JSContext,*mut c_void)>,
    JS_IsError:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue) -> c_int>,
    JS_NewStringLen:Symbol<'static,unsafe extern fn(*mut JSContext,*const c_char,usize) -> JSValue>,
    JS_NewArrayBufferCopy:Symbol<'static,unsafe extern fn(*mut JSContext,*const u8,usize) -> JSValue>,
    JS_NewArray:Symbol<'static,unsafe extern fn(*mut JSContext) -> JSValue>,
    JS_DefinePropertyValueUint32:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue,u32,JSValue,c_int) -> c_int>,
    JS_NewObject:Symbol<'static,unsafe extern fn(*mut JSContext) -> JSValue>,
    JS_SetModuleExport:Symbol<'static,unsafe extern fn(*mut JSContext,*mut JSModuleDef,*const c_char,JSValue) -> c_int>,
    JS_AddModuleExport:Symbol<'static,unsafe extern fn(*mut JSContext,*mut JSModuleDef,*const c_char) -> c_int>,
    JS_Call:Symbol<'static,unsafe extern fn(*mut JSContext,JSValue,JSValue,c_int,*mut JSValue) -> JSValue>,
    JS_SetContextOpaque:Symbol<'static,unsafe extern fn(*mut JSContext,*mut c_void)>,
    JS_GetContextOpaque:Symbol<'static,unsafe extern fn(*mut JSContext) -> *mut c_void>,
    JS_IsLiveObject:Symbol<'static,unsafe extern fn(*mut JSRuntime,JSValue) -> c_int>,
    __JS_FreeValueRT:Symbol<'static,unsafe extern fn(*mut JSRuntime,JSValue)>,
}

lazy_static! {
    static ref library:Library =  {
       //let mut cur_dir = String::from(env::current_dir().unwrap().to_str().unwrap());
       //cur_dir.push_str("\\libquickjs.dll");
       Library::new("./libquickjs.dll").expect("./libquickjs.dll")
    }; 
    static ref libraryInfo:LibraryInfo = unsafe {
       LibraryInfo {
        JS_NewRuntime: library.get(b"JS_NewRuntime").unwrap(),
        JS_NewContext: library.get(b"JS_NewContext").unwrap(),
        JS_AddIntrinsicBaseObjects: library.get(b"JS_AddIntrinsicBaseObjects").unwrap(),
        JS_AddIntrinsicDate: library.get(b"JS_AddIntrinsicDate").unwrap(),
        JS_AddIntrinsicEval: library.get(b"JS_AddIntrinsicEval").unwrap(),
        JS_AddIntrinsicStringNormalize:library.get(b"JS_AddIntrinsicStringNormalize").unwrap(),
        JS_AddIntrinsicRegExpCompiler:library.get(b"JS_AddIntrinsicRegExpCompiler").unwrap(),
        JS_AddIntrinsicRegExp:library.get(b"JS_AddIntrinsicRegExp").unwrap(),
        JS_AddIntrinsicJSON:library.get(b"JS_AddIntrinsicJSON").unwrap(),
        JS_AddIntrinsicProxy:library.get(b"JS_AddIntrinsicProxy").unwrap(),
        JS_AddIntrinsicMapSet:library.get(b"JS_AddIntrinsicMapSet").unwrap(),
        JS_AddIntrinsicTypedArrays:library.get(b"JS_AddIntrinsicTypedArrays").unwrap(),
        JS_AddIntrinsicPromise:library.get(b"JS_AddIntrinsicPromise").unwrap(),
        JS_Eval:library.get(b"JS_Eval").unwrap(),
        JS_GetException:library.get(b"JS_GetException").unwrap(),
        JS_GetGlobalObject:library.get(b"JS_GetGlobalObject").unwrap(),
        JS_NewCFunction2:library.get(b"JS_NewCFunction2").unwrap(),
        JS_DefinePropertyValueStr:library.get(b"JS_DefinePropertyValueStr").unwrap(),
        JS_SetPropertyFunctionList:library.get(b"JS_SetPropertyFunctionList").unwrap(),
        JS_NewCModule:library.get(b"JS_NewCModule").unwrap(),
        JS_AddModuleExportList:library.get(b"JS_AddModuleExportList").unwrap(),
        JS_SetModuleExportList:library.get(b"JS_SetModuleExportList").unwrap(),
        JS_FreeContext:library.get(b"JS_FreeContext").unwrap(),
        JS_Require:library.get(b"JS_Require").unwrap(),
        JS_NewClassID:library.get(b"JS_NewClassID").unwrap(),
        JS_NewClass:library.get(b"JS_NewClass").unwrap(),
        JS_NewObjectClass:library.get(b"JS_NewObjectClass").unwrap(),
        JS_SetOpaque:library.get(b"JS_SetOpaque").unwrap(),
        JS_GetOpaque:library.get(b"JS_GetOpaque").unwrap(),
        JS_SetModuleLoaderFunc:library.get(b"JS_SetModuleLoaderFunc").unwrap(),
        JS_ThrowReferenceError:library.get(b"JS_ThrowReferenceError").unwrap(),
        JS_FreeRuntime:library.get(b"JS_FreeRuntime").unwrap(),
        __JS_FreeValue:library.get(b"__JS_FreeValue").unwrap(),
        JS_ToCStringLen2:library.get(b"JS_ToCStringLen2").unwrap(),
        JS_FreeCString:library.get(b"JS_FreeCString").unwrap(),
        JS_IsFunction:library.get(b"JS_IsFunction").unwrap(),
        JS_IsArray:library.get(b"JS_IsArray").unwrap(),
        JS_GetPropertyStr:library.get(b"JS_GetPropertyStr").unwrap(),
        JS_GetPropertyUint32:library.get(b"JS_GetPropertyUint32").unwrap(),
        JS_GetOwnPropertyNames:library.get(b"JS_GetOwnPropertyNames").unwrap(),
        JS_GetPropertyInternal:library.get(b"JS_GetPropertyInternal").unwrap(),
        JS_AtomToString:library.get(b"JS_AtomToString").unwrap(),
        JS_FreeAtom:library.get(b"JS_FreeAtom").unwrap(),
        js_free:library.get(b"js_free").unwrap(),
        JS_IsError:library.get(b"JS_IsError").unwrap(),
        JS_NewStringLen:library.get(b"JS_NewStringLen").unwrap(),
        JS_NewArrayBufferCopy:library.get(b"JS_NewArrayBufferCopy").unwrap(),
        JS_NewArray:library.get(b"JS_NewArray").unwrap(),
        JS_DefinePropertyValueUint32:library.get(b"JS_DefinePropertyValueUint32").unwrap(),
        JS_NewObject:library.get(b"JS_NewObject").unwrap(),
        JS_SetModuleExport:library.get(b"JS_SetModuleExport").unwrap(),
        JS_AddModuleExport:library.get(b"JS_AddModuleExport").unwrap(),
        JS_Call:library.get(b"JS_Call").unwrap(),
        JS_SetContextOpaque:library.get(b"JS_SetContextOpaque").unwrap(),
        JS_GetContextOpaque:library.get(b"JS_GetContextOpaque").unwrap(),
        JS_IsLiveObject:library.get(b"JS_IsLiveObject").unwrap(),
        __JS_FreeValueRT:library.get(b"__JS_FreeValueRT").unwrap(),
       }
    };
}

pub unsafe fn JS_NewRuntime() -> *mut JSRuntime {
   (libraryInfo.JS_NewRuntime)()
}

pub unsafe fn JS_NewContext(rt:*mut JSRuntime) -> *mut JSContext{
    (libraryInfo.JS_NewContext)(rt)
}

pub unsafe fn JS_AddIntrinsicBaseObjects(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicBaseObjects)(ctx)
}

pub unsafe fn JS_AddIntrinsicDate(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicDate)(ctx)
}

pub unsafe fn JS_AddIntrinsicEval(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicEval)(ctx)
}

pub unsafe fn JS_AddIntrinsicStringNormalize(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicStringNormalize)(ctx)
}

pub unsafe fn JS_AddIntrinsicRegExpCompiler(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicRegExpCompiler)(ctx)
}

pub unsafe fn JS_AddIntrinsicRegExp(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicRegExp)(ctx)
}

pub unsafe fn JS_AddIntrinsicJSON(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicJSON)(ctx)
}

pub unsafe fn JS_AddIntrinsicProxy(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicProxy)(ctx)
}

pub unsafe fn JS_AddIntrinsicMapSet(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicMapSet)(ctx)
}

pub unsafe fn JS_AddIntrinsicTypedArrays(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicTypedArrays)(ctx)
}

pub unsafe fn JS_AddIntrinsicPromise(ctx:*mut JSContext) {
    (libraryInfo.JS_AddIntrinsicPromise)(ctx)
}

pub unsafe fn JS_Eval(ctx:*mut JSContext,input:*const c_char,input_len:usize,filename:*const c_char,eval_flags:c_int) -> JSValue {
    (libraryInfo.JS_Eval)(ctx,input,input_len,filename,eval_flags)
}

pub unsafe fn JS_GetException(ctx:*mut JSContext) -> JSValue {
    (libraryInfo.JS_GetException)(ctx)
}

pub unsafe fn JS_GetGlobalObject(ctx:*mut JSContext) -> JSValue {
    (libraryInfo.JS_GetGlobalObject)(ctx)
}

pub unsafe fn JS_NewCFunction2(ctx:*mut JSContext,func:JSCFunction,name: *const c_char,lenght:c_int,cproto:JSCFunctionEnum,magic:c_int) -> JSValue {
    (libraryInfo.JS_NewCFunction2)(ctx,func,name,lenght,cproto,magic)
}

pub unsafe fn JS_DefinePropertyValueStr(ctx:*mut JSContext,this_obj:JSValue,prop:*const c_char,val:JSValue,flags:c_int) -> c_int {
    (libraryInfo.JS_DefinePropertyValueStr)(ctx,this_obj,prop,val,flags)
}

pub unsafe fn JS_SetPropertyFunctionList(ctx:*mut JSContext,obj:JSValue,tab:*const JSCFunctionListEntry,len:c_int)  {
    (libraryInfo.JS_SetPropertyFunctionList)(ctx,obj,tab,len)
}

pub unsafe fn JS_NewCModule(ctx:*mut JSContext,name_str:*const c_char,func:JSModuleInitFunc) -> *mut JSModuleDef  {
    (libraryInfo.JS_NewCModule)(ctx,name_str,func)
}

pub unsafe fn JS_AddModuleExportList(ctx: *mut JSContext,m: *mut JSModuleDef,tab: *const JSCFunctionListEntry,len:c_int) -> c_int  {
    (libraryInfo.JS_AddModuleExportList)(ctx,m,tab,len)
}

pub unsafe fn JS_SetModuleExportList(ctx: *mut JSContext,m: *mut JSModuleDef,tab: *const JSCFunctionListEntry,len:c_int) -> c_int  {
    (libraryInfo.JS_SetModuleExportList)(ctx,m,tab,len)
}

pub unsafe fn JS_FreeContext(ctx:*mut JSContext) {
    (libraryInfo.JS_FreeContext)(ctx)
}

pub unsafe fn JS_Require(ctx:*mut JSContext,module_name:*mut c_char,js_func:JSValue) -> JSValue {
    (libraryInfo.JS_Require)(ctx,module_name,js_func)
}

pub unsafe fn JS_NewClassID(pclass_id: *mut JSClassID) -> JSClassID {
    (libraryInfo.JS_NewClassID)(pclass_id)
}

pub unsafe fn JS_NewClass( rt: *mut JSRuntime,class_id: JSClassID,class_def: *const JSClassDef) -> c_int {
    (libraryInfo.JS_NewClass)(rt,class_id,class_def)
}

pub unsafe fn JS_NewObjectClass(ctx: *mut JSContext, class_id:c_int) -> JSValue {
    (libraryInfo.JS_NewObjectClass)(ctx,class_id)
}

pub unsafe fn JS_SetOpaque(obj: JSValue, opaque: *mut c_void) {
    (libraryInfo.JS_SetOpaque)(obj,opaque)
}

pub unsafe fn JS_GetOpaque(obj: JSValue, class_id: JSClassID) -> *mut c_void {
    (libraryInfo.JS_GetOpaque)(obj,class_id)
}

pub unsafe fn JS_SetModuleLoaderFunc(rt: *mut JSRuntime,module_normalize: JSModuleNormalizeFunc,module_loader: JSModuleLoaderFunc,opaque: *mut c_void) {
    (libraryInfo.JS_SetModuleLoaderFunc)(rt,module_normalize,module_loader,opaque)
}

pub unsafe fn JS_ThrowReferenceError(ctx: *mut JSContext,fmt: *const c_char,fmt2:*const c_char) -> JSValue  {
    (libraryInfo.JS_ThrowReferenceError)(ctx,fmt,fmt2)
}

pub unsafe fn JS_FreeRuntime(rt:*mut JSRuntime) {
    (libraryInfo.JS_FreeRuntime)(rt)
}

pub unsafe fn __JS_FreeValue(rt:*mut JSContext,v: JSValue) {
    (libraryInfo.__JS_FreeValue)(rt,v)
}

pub unsafe fn JS_ToCStringLen2(ctx: *mut JSContext,plen: *mut usize,val1: JSValue,cesu8: c_int) -> *const c_char {
    (libraryInfo.JS_ToCStringLen2)(ctx,plen,val1,cesu8)
}

pub unsafe fn JS_FreeCString(ctx: *mut JSContext,ptr:*const c_char) {
    (libraryInfo.JS_FreeCString)(ctx,ptr)
}

pub unsafe fn JS_IsFunction(ctx: *mut JSContext,val:JSValue) -> c_int {
    (libraryInfo.JS_IsFunction)(ctx,val)
}

pub unsafe fn JS_IsArray(ctx: *mut JSContext,val:JSValue) -> c_int {
    (libraryInfo.JS_IsArray)(ctx,val)
}

pub unsafe fn JS_GetPropertyStr(ctx: *mut JSContext,obj: JSValue,prop: *const c_char) -> JSValue {
    (libraryInfo.JS_GetPropertyStr)(ctx,obj,prop)
}

pub unsafe fn JS_GetPropertyUint32(ctx: *mut JSContext,obj: JSValue,idx: u32) -> JSValue {
    (libraryInfo.JS_GetPropertyUint32)(ctx,obj,idx)
}

pub unsafe fn JS_GetOwnPropertyNames(ctx: *mut JSContext,ptab: *mut *mut JSPropertyEnum,plen: *mut u32,obj: JSValue,flags:c_int) -> c_int {
    (libraryInfo.JS_GetOwnPropertyNames)(ctx,ptab,plen,obj,flags)
}

pub unsafe fn JS_GetPropertyInternal(ctx: *mut JSContext,obj: JSValue,atom: JSAtom,receiver: JSValue,throw_ref_error:c_int) -> JSValue {
    (libraryInfo.JS_GetPropertyInternal)(ctx,obj,atom,receiver,throw_ref_error)
}

pub unsafe fn JS_AtomToString(ctx: *mut JSContext, atom: JSAtom) -> JSValue {
    (libraryInfo.JS_AtomToString)(ctx,atom)
}

pub unsafe fn JS_FreeAtom(ctx: *mut JSContext, atom: JSAtom) -> JSValue {
    (libraryInfo.JS_FreeAtom)(ctx,atom)
}

pub unsafe fn js_free(ctx: *mut JSContext, ptr: *mut c_void) {
    (libraryInfo.js_free)(ctx,ptr)
}

pub unsafe fn JS_IsError(ctx: *mut JSContext, val: JSValue) -> c_int {
    (libraryInfo.JS_IsError)(ctx,val)
}

pub unsafe fn JS_NewStringLen(ctx: *mut JSContext,str1: *const c_char,len1: usize) -> JSValue {
    (libraryInfo.JS_NewStringLen)(ctx,str1,len1)
}

pub unsafe fn JS_NewArrayBufferCopy(ctx: *mut JSContext, buf: *const u8, len: usize) -> JSValue {
    (libraryInfo.JS_NewArrayBufferCopy)(ctx,buf,len)
}

pub unsafe fn JS_NewArray(ctx: *mut JSContext) -> JSValue {
    (libraryInfo.JS_NewArray)(ctx)
}

pub unsafe fn JS_DefinePropertyValueUint32(ctx: *mut JSContext,this_obj: JSValue,idx: u32,val: JSValue,flags:c_int) -> c_int {
    (libraryInfo.JS_DefinePropertyValueUint32)(ctx,this_obj,idx,val,flags)
}

pub unsafe fn JS_NewObject(ctx: *mut JSContext) -> JSValue {
    (libraryInfo.JS_NewObject)(ctx)
}

pub unsafe fn JS_SetModuleExport(ctx: *mut JSContext,m: *mut JSModuleDef,export_name: *const c_char,val: JSValue) -> c_int {
    (libraryInfo.JS_SetModuleExport)(ctx,m,export_name,val)
}

pub unsafe fn JS_AddModuleExport(ctx: *mut JSContext,m: *mut JSModuleDef,name_str: *const c_char) -> c_int {
    (libraryInfo.JS_AddModuleExport)(ctx,m,name_str)
}

pub unsafe fn JS_Call( ctx: *mut JSContext,func_obj: JSValue,this_obj: JSValue,argc:c_int,argv: *mut JSValue) -> JSValue {
    (libraryInfo.JS_Call)(ctx,func_obj,this_obj,argc,argv)
}


pub unsafe fn JS_GetContextOpaque(ctx: *mut JSContext) -> *mut c_void {
    (libraryInfo.JS_GetContextOpaque)(ctx)
}

pub unsafe fn JS_SetContextOpaque(ctx: *mut JSContext,opaque:*mut c_void)  {
    (libraryInfo.JS_SetContextOpaque)(ctx,opaque)
}

pub unsafe fn JS_IsLiveObject(rt:*mut JSRuntime,value:JSValue) -> i32 {
    (libraryInfo.JS_IsLiveObject)(rt,value)
}

pub unsafe fn __JS_FreeValueRT(rt:*mut JSRuntime,value:JSValue) {
    (libraryInfo.__JS_FreeValueRT)(rt,value)
}

#[test]
fn test() {
  unsafe {
    let rt = JS_NewRuntime();
    let ctx = JS_NewContext(rt);
    dbg!(ctx);
  }
}